package com.zte.rest;


import com.atlassian.confluence.core.SpaceContentEntityObject;
import com.atlassian.confluence.internal.ContentEntityManagerInternal;
import com.atlassian.confluence.labels.Label;
import com.atlassian.confluence.links.LinkManager;
import com.atlassian.confluence.links.OutgoingLink;
import com.atlassian.confluence.pages.AbstractPage;
import com.atlassian.confluence.pages.Page;
import com.atlassian.confluence.pages.PageManager;
import com.atlassian.confluence.search.ConfluenceIndexer;
import com.atlassian.confluence.setup.settings.SettingsManager;
import com.atlassian.confluence.spaces.Space;
import com.atlassian.confluence.spaces.SpaceManager;
import com.atlassian.plugin.spring.scanner.annotation.imports.ComponentImport;
import com.google.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.inject.Inject;
import javax.inject.Named;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


@Path("/page")
@Named("pageService")
public class PageService {

    private static final Logger log = LoggerFactory.getLogger(PageService.class);

    @ComponentImport
    protected SpaceManager spaceManager;

    @ComponentImport
    protected PageManager pageManager;

    @ComponentImport
    protected LinkManager linkManager;

    @ComponentImport
    protected ContentEntityManagerInternal contentEntityManagerInternal;

    @ComponentImport
    protected SettingsManager settingsManager;

    @ComponentImport
    protected ConfluenceIndexer indexer;

    protected String baseUrl;

    @Inject
    public PageService(SpaceManager spaceManager, ConfluenceIndexer indexer, PageManager pageManager, LinkManager linkManager, ContentEntityManagerInternal contentEntityManagerInternal, SettingsManager settingsManager) {
        this.spaceManager = spaceManager;
        this.indexer = indexer;
        this.pageManager = pageManager;
        this.linkManager = linkManager;
        this.contentEntityManagerInternal = contentEntityManagerInternal;
        this.settingsManager = settingsManager;
        this.baseUrl = settingsManager.getGlobalSettings().getBaseUrl();
    }

    @Path("getPageTree")
    @GET
    @Produces({MediaType.APPLICATION_JSON})
    public Response getPageTree(@QueryParam("pageId") long pageId) {
        Map result = new HashMap();

        try {
            List<Map> list = new ArrayList<>();
            getChildren(pageId, list);

            result.put("results", list);
            result.put("size", list.size());
            result.put("status", 0);

        } catch (Exception e) {
            result.put("results", new ArrayList());
            result.put("size", 0);
            result.put("status", 1);
        }
        return Response.ok(result).build();
    }


    @Path("getPageLinks")
    @GET
    @Produces({MediaType.APPLICATION_JSON})
    public Response getPageLinks(@QueryParam("pageId") long pageId) {
        Map result = new HashMap();
        try {
            Page page = pageManager.getPage(pageId);
            List<OutgoingLink> allLinks = linkManager.getIncomingLinksToContent(page);
            allLinks = getUniqueUndeletedIncomingLinks(page, allLinks);
            List<Map> list = new ArrayList<>();
            for (OutgoingLink link : allLinks) {
                Map map = new HashMap();
                map.put("title", link.getSourceContent().getDisplayTitle());
                map.put("url", baseUrl + link.getSourceContent().getUrlPath());
                list.add(map);
            }
            result.put("size", allLinks.size());
            result.put("links", list);
        } catch (Exception e) {
            log.error("获取链接出错 : {}", e.getMessage());
            result.put("code", "111111");
            result.put("message", "获取链接出错");
            return Response.ok(result).build();
        }
        result.put("code", "000000");
        result.put("message", "success");
        return Response.ok(result).build();
    }

    @Path("getPageReferences")
    @GET
    @Produces({MediaType.APPLICATION_JSON})
    public Response getPageReferences(@QueryParam("pageId") long pageId) {
        Map result = new HashMap();
        try {
            Page page = pageManager.getPage(pageId);

            List<OutgoingLink> allLinks = page.getOutgoingLinks();
            List<Map> list = new ArrayList<>();
            for (OutgoingLink link : allLinks) {
                Map map = new HashMap();
                if (link.isUrlLink()) {
                    map.put("title", link.getUrlLink());
                    map.put("url", link.getUrlLink());
                } else {
                    Page outgoingLink = pageManager.getPage(link.getDestinationSpaceKey(), link.getDestinationPageTitle());
                    map.put("title", link.getDestinationPageTitle());
                    map.put("url", baseUrl + outgoingLink.getUrlPath());
                }
                list.add(map);
            }
            result.put("size", allLinks.size());
            result.put("links", list);
        } catch (Exception e) {
            log.error("获取链接出错 : {}", e.getMessage());
            result.put("code", "111111");
            result.put("message", "获取链接出错");
            return Response.ok(result).build();
        }
        result.put("code", "000000");
        result.put("message", "success");
        return Response.ok(result).build();
    }

    @Path("getPageLabels")
    @GET
    @Produces({MediaType.APPLICATION_JSON})
    public Response getPageLabels(@QueryParam("pageId") long pageId) {
        Map result = new HashMap();
        try {
            Page page = pageManager.getPage(pageId);
            List<Label> labels = page.getLabels();
            List<Map> list = new ArrayList<>();
            for (Label label : labels) {
                Map map = new HashMap();
                map.put("name", label.getName());
                list.add(map);
            }
            result.put("size", labels.size());
            result.put("labels", list);
        } catch (Exception e) {
            log.error("获取链接出错 : {}", e.getMessage());
            result.put("code", "111111");
            result.put("message", "获取链接出错");
            return Response.ok(result).build();
        }
        result.put("code", "000000");
        result.put("message", "success");
        return Response.ok(result).build();
    }

    @Path("reindexSpace")
    @GET
    @Produces({MediaType.APPLICATION_JSON})
    public Response reindexSpace(@QueryParam("space") String key) {
        Map result = new HashMap();
        try {
            Space space = spaceManager.getSpace(key);
            Page home = space.getHomePage();
            this.reindexPage(home);
        } catch (Exception e) {
            log.error("页面重建索引 : {}", e.getMessage());
            result.put("code", "111111");
            result.put("message", "页面重建索引");
            return Response.ok(result).build();
        }
        result.put("code", "000000");
        result.put("message", "success");
        return Response.ok(result).build();
    }

    @Path("reindexPage")
    @GET
    @Produces({MediaType.APPLICATION_JSON})
    public Response reindexPage(@QueryParam("pageId") long pageId) {
        Map result = new HashMap();
        try {
            Page page = pageManager.getPage(pageId);
            this.reindexPage(page);
        } catch (Exception e) {
            log.error("页面重建索引 : {}", e.getMessage());
            result.put("code", "111111");
            result.put("message", "页面重建索引");
            return Response.ok(result).build();
        }
        result.put("code", "000000");
        result.put("message", "success");
        return Response.ok(result).build();
    }


    @Path("getPageInfo")
    @GET
    @Produces({MediaType.APPLICATION_JSON})
    public Response getPageInfo(@QueryParam("pageId") long pageId) {
        Map result = new HashMap();
        try {
            Page page = pageManager.getPage(pageId);

            Map map = new HashMap();
            map.put("content", page.getBodyAsString());
            map.put("version", page.getVersion() + 1);
            map.put("title", page.getTitle());
            result.put("info", map);
        } catch (Exception e) {
            log.error("获取页面信息 : {}", e.getMessage());
            result.put("code", "111111");
            result.put("message", "获取页面信息");
            return Response.ok(result).build();
        }
        result.put("code", "000000");
        result.put("message", "success");
        return Response.ok(result).build();
    }

    private void getChildren(long pageId, List<Map> list) {
        Page page = pageManager.getPage(pageId);
        for (Page p : page.getDescendants()) {
            Map map = new HashMap();
            map.put("id", p.getIdAsString());
            map.put("lastModificationDate", p.getLastModificationDate());
            map.put("version", p.getVersion());
            list.add(map);
        }
    }

    private List<OutgoingLink> getUniqueUndeletedIncomingLinks(AbstractPage page, List<OutgoingLink> allLinks) {
        Set<OutgoingLink> incomingLinks = new HashSet<>();
        for (OutgoingLink link : allLinks) {
            Object sourceContent = link.getSourceContent();
            if (sourceContent instanceof SpaceContentEntityObject) {
                SpaceContentEntityObject spaceContentEntityObject = (SpaceContentEntityObject) sourceContent;
                if (!spaceContentEntityObject.isDraft() && !spaceContentEntityObject.isDeleted() && !link.isFrom(page)) {
                    incomingLinks.add(link);
                }
            }
        }
        return Lists.newArrayList(incomingLinks);
    }

    private void reindexPage(Page root) {
        List<Page> list = root.getDescendants();
        if (list.isEmpty()) {
            this.indexer.reIndex(root);
        } else {
            int threadSum = list.size() % 100 == 0 ? list.size() / 100 : list.size() / 100 + 1;
            ExecutorService pool = Executors.newFixedThreadPool(threadSum);
            for (int i = 0; i < threadSum; i++) {
                List<Page> subList;
                if (i == threadSum - 1) {
                    subList = list.subList(i * 100, list.size());
                } else {
                    subList = list.subList(i * 100, (i + 1) * 100);
                }
//                pool.submit(new IndexTask(subList, this.indexer));
            }
        }

    }

}